package com.yalantis.phoenix.refresh_view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;

import com.yalantis.phoenix.PullToRefreshView;
import com.yalantis.phoenix.R;
import com.yalantis.phoenix.util.Utils;

import java.util.ArrayList;

/**
 * Created by Oleksii Shliama on 22/12/2014.
 * https://dribbble.com/shots/1650317-Pull-to-Refresh-Rentals
 */
public class SunRefreshView extends BaseRefreshView implements Animatable {

    private static final float SCALE_START_PERCENT = 0.5f;
    private static final int ANIMATION_DURATION = 1000;

    private final static float SKY_RATIO = 0.65f;

    private final static float TOWN_RATIO = 0.22f;
    private static final float TOWN_INITIAL_SCALE = 1.20f;
    private static final float TOWN_FINAL_SCALE = 1.30f;

    private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();

    private PullToRefreshView mParent;
    private Matrix mMatrix;
    private Animation mAnimation;

    private int mTop;
    private int mScreenWidth;

    private int mSkyHeight;

    private int mTownHeight;
    private float mTownInitialTopOffset;
    private float mTownFinalTopOffset;
    private float mTownMoveOffset;

    private float mPercent = 0.0f;
    private float mRotate = 0.0f;

    private Bitmap mRefreshIcon;
    private Bitmap mRefreshIcon1;
    private Bitmap mRefreshIcon2;

    private boolean isRefreshing = false;

    // 刷新的图标的宽高
    private int refreshIconWidth;
    private int refreshIconHeight;

    // 下拉刷新文字画笔
    private Paint textPain;

    // 当前应当播放图片的下标
    private int currentIndex = 0;

    // 刷新icon的播放图片list
    private ArrayList<Bitmap> iconList = new ArrayList();

    public SunRefreshView(Context context, final PullToRefreshView parent) {
        super(context, parent);
        mParent = parent;
        mMatrix = new Matrix();

        setupAnimations();
        parent.post(new Runnable() {
            @Override
            public void run() {
                initiateDimens(parent.getWidth());
            }
        });
    }

    public void initiateDimens(int viewWidth) {
        if (viewWidth <= 0 || viewWidth == mScreenWidth) return;

        mScreenWidth = viewWidth;
        mSkyHeight = (int) (SKY_RATIO * mScreenWidth);

        mTownHeight = (int) (TOWN_RATIO * mScreenWidth) - Utils.convertDpToPixel(getContext(), 10);
        mTownInitialTopOffset = (mParent.getTotalDragDistance() - mTownHeight * TOWN_INITIAL_SCALE);
        mTownFinalTopOffset = (mParent.getTotalDragDistance() - mTownHeight * TOWN_FINAL_SCALE);
        mTownMoveOffset = Utils.convertDpToPixel(getContext(), 10);

        mTop = -mParent.getTotalDragDistance();

        createBitmaps();
    }

    private void createBitmaps() {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        refreshIconWidth = Utils.convertDpToPixel(getContext(), 45);
        refreshIconHeight = Utils.convertDpToPixel(getContext(), 40);
        options.inPreferredConfig = Bitmap.Config.RGB_565;

        mRefreshIcon = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.sky, options);
        mRefreshIcon = Bitmap.createScaledBitmap(mRefreshIcon, refreshIconWidth, refreshIconHeight, true);

        mRefreshIcon1 = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.buildings, options);
        mRefreshIcon1 = Bitmap.createScaledBitmap(mRefreshIcon1, refreshIconWidth, refreshIconHeight, true);

        mRefreshIcon2 = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.sun, options);
        mRefreshIcon2 = Bitmap.createScaledBitmap(mRefreshIcon2, refreshIconWidth, refreshIconHeight, true);

        if (iconList.size() == 0) {
            iconList.add(mRefreshIcon);
            iconList.add(mRefreshIcon1);
            iconList.add(mRefreshIcon2);
        }
    }

    @Override
    public void setPercent(float percent, boolean invalidate) {
        setPercent(percent);
        if (invalidate) setRotate(percent);
    }

    @Override
    public void offsetTopAndBottom(int offset) {
        mTop += offset;
        invalidateSelf();
    }

    @Override
    public void draw(Canvas canvas) {
        if (mScreenWidth <= 0) return;

        final int saveCount = canvas.save();

        canvas.translate(0, mTop);
        canvas.clipRect(0, -mTop, mScreenWidth, mParent.getTotalDragDistance());

        drawRefreshIcon(canvas, currentIndex);

        canvas.restoreToCount(saveCount);
    }

    private void drawRefreshIcon(Canvas canvas, int currentIndex) {
        Matrix matrix = mMatrix;
        matrix.reset();

        float dragPercent = Math.min(1f, Math.abs(mPercent));

        float townScale;
        float townTopOffset;
        float townMoveOffset;
        float scalePercentDelta = dragPercent - SCALE_START_PERCENT;
        if (scalePercentDelta > 0) {
            /**
             * Change townScale between {@link #TOWN_INITIAL_SCALE} and {@link #TOWN_FINAL_SCALE} depending on {@link #mPercent}
             * Change townTopOffset between {@link #mTownInitialTopOffset} and {@link #mTownFinalTopOffset} depending on {@link #mPercent}
             */
            float scalePercent = scalePercentDelta / (1.0f - SCALE_START_PERCENT);
            townScale = TOWN_INITIAL_SCALE + (TOWN_FINAL_SCALE - TOWN_INITIAL_SCALE) * scalePercent;
            townTopOffset = mTownInitialTopOffset - (mTownFinalTopOffset - mTownInitialTopOffset) * scalePercent;
            townMoveOffset = mTownMoveOffset * (1.0f - scalePercent);
        } else {
            float scalePercent = dragPercent / SCALE_START_PERCENT;
            townScale = TOWN_INITIAL_SCALE;
            townTopOffset = mTownInitialTopOffset;
            townMoveOffset = mTownMoveOffset * scalePercent;
        }

        float offsetX = mScreenWidth / 2.0f - refreshIconWidth / 2.0f;
        float refreshIconOffsetX = mScreenWidth / 2.0f - Utils.convertDpToPixel(getContext(), 19.5f);
        float offsetY = (1.0f - dragPercent) * mParent.getTotalDragDistance() // Offset canvas moving
                + townTopOffset
                - mTownHeight * (townScale - 1.0f) / 2 // Offset town scaling
                + townMoveOffset; // Give it a little move
        float refreshIconOffsetY = offsetY + refreshIconHeight + Utils.convertDpToPixel(getContext(), 33);

        if (textPain == null) {
            textPain = new Paint();
            textPain.setColor(Color.WHITE);
            textPain.setTextSize(Utils.convertDpToPixel(getContext(), 13));
        }

        if (isRefreshing) {
            canvas.drawText("正在请求", refreshIconOffsetX, refreshIconOffsetY, textPain);
        } else {
            if (Math.abs(mPercent) < 1) {
                canvas.drawText("下拉刷新", refreshIconOffsetX, refreshIconOffsetY, textPain);
            } else {
                canvas.drawText("松开加载", refreshIconOffsetX, refreshIconOffsetY, textPain);
            }
        }

        matrix.postScale(townScale, townScale);
        matrix.postTranslate(offsetX, offsetY);

        canvas.drawBitmap(iconList.get(currentIndex), matrix, null);

    }

    public void setPercent(float percent) {
        mPercent = percent;
    }

    public void setRotate(float rotate) {
        mRotate = rotate;
        invalidateSelf();
    }

    public void resetOriginals() {
        setPercent(0);
        setRotate(0);
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, mSkyHeight + top);
    }

    @Override
    public boolean isRunning() {
        return false;
    }

    @Override
    public void start() {
        mAnimation.reset();
        isRefreshing = true;
        new Thread() {
            @Override
            public void run() {
                while (isRefreshing) {
                    try {
                        currentIndex++;
                        if (currentIndex >= iconList.size()) {
                            currentIndex = 0;
                        }
                        sleep(180);
                    } catch (Exception e) {
                        isRefreshing = false;
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        mParent.startAnimation(mAnimation);
    }

    @Override
    public void stop() {
        mParent.clearAnimation();
        isRefreshing = false;
        currentIndex = 0;
        resetOriginals();
    }

    private void setupAnimations() {
        mAnimation = new Animation() {
            @Override
            public void applyTransformation(float interpolatedTime, Transformation t) {
                setRotate(interpolatedTime);
            }
        };
        mAnimation.setRepeatCount(Animation.INFINITE);
        mAnimation.setRepeatMode(Animation.RESTART);
        mAnimation.setInterpolator(LINEAR_INTERPOLATOR);
        mAnimation.setDuration(ANIMATION_DURATION);
    }

}
